package com.oktest.measure.ui.fragment

import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.CheckBox
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.cali.common.kt.*
import com.cali.libcore.base.BaseFragment
import com.cali.libcore.dialog.alertdialog.helper.CommonDialogHelper
import com.cali.libcore.http.RetrofitManagement
import com.cali.libcore.view.pop.CommonPopupWindow
import com.chad.library.adapter.base.entity.node.BaseNode
import com.jakewharton.rxbinding2.view.RxView
import com.oktest.measure.BuildConfig
import com.oktest.measure.MyApp
import com.oktest.measure.MyApp.Companion.currentTaskId
import com.oktest.measure.R
import com.oktest.measure.entity.*
import com.oktest.measure.http.Api
import com.oktest.measure.kt.*
import com.oktest.measure.ui.adapter.WorkTreeAdapter
import com.oktest.measure.ui.dialog.InputDialog
import com.oktest.measure.ui.fragment.work.FeedbackFragment
import com.oktest.measure.ui.fragment.work.FeedbackFragment.Companion.MEASURE_ID
import com.oktest.measure.ui.fragment.work.TestHistoryFragment
import com.oktest.measure.ui.fragment.work.TestOverFragment
import com.oktest.measure.xml.XmlPullHelper
import kotlinx.android.synthetic.main.download_layout_dialog_default.view.*
import kotlinx.android.synthetic.main.fragment_main_work.*
import kotlinx.android.synthetic.main.include_work_head_layout.*
import kotlinx.android.synthetic.main.pop_work_item_layout.view.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.File
import java.io.FileInputStream
import java.util.concurrent.TimeUnit
import kotlin.collections.set

/**
 * @Author hhh
 * @Date 2020/9/16
 */
class WorkFragment : BaseFragment() {

    private val api by lazy {
        RetrofitManagement.instance.getService(Api::class.java)
    }
    private val measureCheckList = hashSetOf<Long>()

    private val dialogHelper by lazy {
        CommonDialogHelper(context!!)
    }

    private var popupWindow: CommonPopupWindow? = null
    private val workTreeAdapter by lazy {
        WorkTreeAdapter().also {
            workRecyclerView.layoutManager = LinearLayoutManager(context)
            workRecyclerView.adapter = it
            workRecyclerView.emptyView(msg = "没有检测到并网调试数据\n请到首页下载并网调试任务") {

            }
            it.setOnItemChildClickListener { _, view, position ->
                // type checkBox
                when (view.id) {
                    R.id.sub1BoxCheck -> sub1Check(position)
                    R.id.sub2BoxCheck -> sub2Check(position)
                    R.id.tvFeedback -> feedback(position)
                    R.id.etValue -> textChange(position)
                }
            }
        }
    }

    private fun textChange(position: Int) {
        val telemetry = workTreeAdapter.getItem(position) as Measure
        // 防止被恢复
        val type = telemetry.parentType()
        val inputDialog = InputDialog(activity!!,content = telemetry.scv())
        inputDialog.show() {
            workTreeAdapter.close(type)
            if (telemetry.sv.isNotEmpty()) {
                telemetry.sv = it
            } else {
                telemetry.sc = it
            }
            MyApp.roomDatabase.measureDao().update(telemetry)
            workTreeAdapter.open(type)
            Log.i("WorkFragment", "$it $position")
        }
    }

    override fun getLayoutId(): Int {
        return R.layout.fragment_main_work
    }

    //
    private var isExpand = false

    override fun initData(savedInstanceState: Bundle?) {
        initListener()
        initToolbarMenu()
        initTreeRecyclerView()
        initSearch()
        initRegister()
        initRefresh()
    }

    // 刷新
    private fun initRefresh() {
        refreshLayout.setOnRefreshListener {
            launch {
                syncMeasure()
                initTreeRecyclerView()
                it.finishRefresh(true)
            }
        }
    }

    // 循环请求
    private fun startCheckResult(ids: List<Long>) = launch {
        toast("正在请求调试结果")
        var delayTotal = 0
        val resultJob = this
        while (isActive) {
            delay(3 * 1000)
            val map = hashMapOf("id" to currentTaskId)
            val checkResult = resultTryContext {
                api.checkResult(map.jsonBody()).execute().body()
            }
            if (checkResult.code == API_SUCCESS_CODE && checkResult.data != null) {
                refreshCheckResult(checkResult.data)
                resultJob.cancel()
            }
            delayTotal += 3
            "delay=$delayTotal,mid=,size=${ids.size}".debugLogInfo(block = { "okhttp" })
            if (delayTotal >= WORK_HTTP_TIMEOUT) {
                resultJob.cancel()
            }
        }
    }
    private val lockMutex = Mutex()
    // 刷新check结果 协程同步
    private suspend fun refreshCheckResult(data: List<MeasureResult?>?) = lockMutex.withLock {
        val typeResult = hashSetOf<Long>()
        val measureResult = arrayListOf<Measure>()
        val measureDao = MyApp.roomDatabase.measureDao()
        // 保存数据
        withContext(Dispatchers.IO) {
            data?.filterNotNull()?.forEach {
                typeResult.add(it.mid)
                measureDao.load(it.measureId)?.apply {
                    isSuccessful = it.status == 1
                    isDebugging = true
                    time = System.currentTimeMillis().toString()
                    errorMsg = it.errMsg
                    measureResult.add(this)
                }
            }
        }
        val typeDao = MyApp.roomDatabase.typeDao()
        // 刷新页面
        typeResult.forEach {
            typeDao.load(it)?.apply {
                workTreeAdapter.jobClose(this)
            }
        }
        measureDao.update(measureResult)
        typeResult.forEach {
            typeDao.load(it)?.apply {
                workTreeAdapter.jobOpen(this)
            }
        }
        toast("调试结果已更新")
        // 更新top
        initTopLayout()
    }

    private fun initRegister() {
        registerEventSimple(EVENT_XML_DOWNLOAD) {
            initDownloadFile(it.info)
        }
        registerEventSimple(EVENT_HOME_TASK_GET){
            initTreeRecyclerView()
        }
    }

    private fun initListener() {
        twoAllTask.setOnClickListener {
            if (BuildConfig.DEBUG) {
                launch {
                    syncMeasure()
                }
            }
        }
        // 设置可见
        if (MyApp.taskIsReceived()) {
            fabReceived.gone()
            fabUpload.visible()
        }
        // 确认接收
        fabReceived.setOnClickListener {
            showDialog()
        }
        // 上传
        fabUpload.setOnClickListener {
            uploadMeasureCheck()
        }
        // 当前点表位置
        fabCurrentWork.setOnClickListener {
            // 滑动到最新位置
            scrollPosition()
        }
        // 展开折叠
        val subscribe = RxView.clicks(fabExpand)
            .throttleFirst(2, TimeUnit.SECONDS)
            .subscribe {
                if (isExpand) closeTypes() else openTypes()
            }
    }

    private fun showDialog() {
        if (currentTaskId == 0L) {
            toast("请到首页下载任务")
            return
        }
        val receivedLayout = View.inflate(context, R.layout.download_layout_dialog_default, null)
        receivedLayout?.apply {
            dialogContent.text = "确定接收该任务吗？"
            dialogTitle.text = "温馨提示"
            btnCancel.setOnClickListener {
                dialogHelper.dismiss()
            }
            btnOk.setOnClickListener {
                dialogHelper.dismiss()
                received()
            }
        }
        dialogHelper.show(receivedLayout, false, isMath = false)
    }

    // 接收任务
    private fun received() = launch {
        val received = resultTryContext {
            val map = hashMapOf("id" to currentTaskId)
            api.taskReceived(map.jsonBody()).execute().body()
        }
        // 保存确认接收任务
        if (received.code == API_SUCCESS_CODE) {
            fabReceived.gone()
            fabUpload.visible()
            val homeTaskDao = MyApp.roomDatabase.homeTaskDao()
            homeTaskDao.query(currentTaskId.toString())?.apply {
                this.isReceived = true
                homeTaskDao.update(this)
            }
            // 刷新
            workTreeAdapter.notifyDataSetChanged()
        } else {
            error(received)
        }
    }

    private fun scrollPosition(smooth: Boolean = false) = launch {
        val measurePosition = resultTryContext {
            val max = workTreeAdapter.data.filterIsInstance<Measure>().filter {
                it.isDebugging
            }.maxByOrNull {
                it.time
            }
            if (max != null) {
                workTreeAdapter.data.indexOf(max)
            } else {
                0
            }
        }
        if (smooth) {
            workRecyclerView.smoothScrollToPosition(measurePosition)
        } else {
            workRecyclerView.scrollToPosition(measurePosition)
        }
    }

    private fun closeTypes() = launch {
        showTip("点表正在收起")
        val types = withContext(Dispatchers.IO) {
            workTreeAdapter.data.filterIsInstance<Type>()
        }
        types.forEach {
            workTreeAdapter.jobClose(it)
        }
        fabExpand.setImageResource(R.drawable.measure_ic_icon_line_collapse)
        isExpand = false
        dismissTip()
    }

    private fun openTypes() = launch {
        showTip("点表正在展开")
        val types = withContext(Dispatchers.IO) {
            workTreeAdapter.data.filterIsInstance<Type>()
        }
        types.forEach {
            workTreeAdapter.jobOpen(it)
        }
        fabExpand.setImageResource(R.drawable.measure_ic_icon_line_expand)
        isExpand = true
        dismissTip()
    }

    private fun types(): List<Type> {
        return MyApp.roomDatabase.typeDao().queryAll()
    }

    // 上传
    private fun uploadMeasureCheck() = launch {
        fabUpload.isEnabled = false
        showTip("数据上传中")
        val result = resultTryContext {
            val array: List<MeasureCheck> = measureCheckList.mapNotNull {
                MyApp.roomDatabase.measureDao().load(it)
            }.map { measure ->
                MeasureCheck().also {
                    it.id = currentTaskId
                    it.mId = measure.typeId
                    it.measureId = measure.id
                    it.value = measure.getMeasureValue()
                    it.type = measure.parentType().type
                    it.soe = ""
                }
            }
            api.check(array.jsonBody()).execute().body()
        }
        dismissTip()
        if (result.code == API_SUCCESS_CODE) {
            val ids = arrayListOf<Long>()
            ids.addAll(measureCheckList)
            measureCheckList.clear()
            startCheckResult(ids)
        }
    }

    private fun initSearch() {
        etWorkSearch.afterTextChange(1000) {
            if (it?.isNotEmpty() == true) {
                startSearch(it.toString())
            } else {
                // 全部关闭
                initTreeRecyclerView()
            }
        }
    }

    private fun initToolbarMenu() {
        toolbarHelper?.apply {
            setTitleText("我的工作")
            setTitleTextColor(Color.WHITE)
            setRightIcon(ContextCompat.getDrawable(mContext, R.drawable.ic_baseline_add_24))
            getRightImage().setOnClickListener {
                showPopWindow(it)
            }
        }
    }

    private fun showPopWindow(it: View?) {
        popupWindow = CommonPopupWindow.Builder(requireActivity())
            .setView(R.layout.pop_work_item_layout)
            .setAnimationStyle(R.style.pop_anim)
            .setBackGroundLevel(1f)
            .setViewOnclickListener { view, _ ->
                view.tvTestHistory.setOnClickListener {
                    popupWindow?.dismiss()
                    startParentBrotherFragment(TestHistoryFragment())
                }
                view.tvTestDone.setOnClickListener {
                    popupWindow?.dismiss()
                    startParentBrotherFragment(TestOverFragment())
                }
            }
            .setOutsideTouchable(true)
            .create()
        popupWindow?.showAsDropDown(it, 200, 0)
    }

    private fun initDownloadFile(info: String) = launch {
        successTryContext {
            val ins = FileInputStream(File(info))
            XmlPullHelper.parseTask(ins)
        }
        // 如果接收过任务
        if (MyApp.taskIsReceived()) {
            syncMeasure()
        }
        initTreeRecyclerView()
    }

    private fun initTopLayout() = launch {
        val typeList = resultListTryContext {
            val result = arrayListOf<Type>()
            MyApp.roomDatabase.apply {
                val devices = xmlDao().devices(currentTaskId)
                devices.forEach {
                    result.addAll(deviceDao().types(it.id))
                }
            }
            result
        }
        typeList.apply {
            // 全部点表
            twoAllTask.setTopText(this.size.toString())
            // 完成
            val doneNum = resultTryContext {
                var num = 0
                this.forEach {
                    if (it.isDone()) {
                        num++
                    }
                }
                num
            }
            twoDone.setTopText("$doneNum")
            // 剩余
            twoResidue.setTopText("${this.size - doneNum}")
        }
    }

    // 只搜索设备或间隔 deviceEntity
    private fun startSearch(searchText: String) = launch {
        showTip("查询中")
        val searchResult = resultListTryContext {
            // 设备
            val result = arrayListOf<BaseNode>()
            devices().filter {
                it.name == searchText
            }.also {
                result.addAll(it)
            }
            // 间隔
            if (result.isEmpty()) {
                types().filter { type ->
                    type.name.contains(searchText)
                }.also {
                    result.addAll(it)
                }
            }
            result
        }
        workTreeAdapter.data.clear()
        workTreeAdapter.setList(searchResult)
        dismissTip()
    }

    private fun devices(): List<Device> {
        return MyApp.roomDatabase.deviceDao().queryAll()
    }

    private fun initTreeRecyclerView() {
        etWorkSearch.setText("")
        measureCheckList.clear()
        workTreeAdapter.setList(arrayListOf())
        MyApp.roomDatabase.xmlDao().load(currentTaskId)?.apply {
            val nodeList = ArrayList<BaseNode>()
            nodeList.addAll(MyApp.roomDatabase.xmlDao().devices(this.id))
            workTreeAdapter.setList(nodeList)
            toolbarHelper?.setTitleText(this.name)
        }
        initTopLayout()
        initMeasureList()
        isExpand = true
    }

    private fun initMeasureList() = launch {
        val result = withContext(Dispatchers.IO) {
            workTreeAdapter.data.filterIsInstance<Measure>().filter {
                it.isChecked && !it.isSuccessful
            }.map {
                it.id
            }
        }
        measureCheckList.addAll(result)
        fabUpload.isEnabled = measureCheckList.isNotEmpty()
    }

    // 反馈
    private fun feedback(position: Int) {
        val measure = workTreeAdapter.getItem(position) as Measure?
        startParentBrotherFragment(FeedbackFragment().also {
            it.arguments = Bundle().also { bundle ->
                bundle.putLong(MEASURE_ID, measure?.id ?: 0)
            }
        })
    }


    private fun sub1Check(position: Int) {
        val sub1Measure = workTreeAdapter.getItem(position) as Measure
        workTreeAdapter.getViewByPosition(position, R.id.sub1BoxCheck)?.apply {
            this as CheckBox
            sub1Measure.isChecked = isChecked
            MyApp.roomDatabase.measureDao().update(sub1Measure)
            addMeasures(isChecked, sub1Measure)
        }
    }

    private fun sub2Check(position: Int) {
        val sub2Measure = workTreeAdapter.getItem(position) as Measure
        workTreeAdapter.getViewByPosition(position, R.id.sub2BoxCheck)?.apply {
            this as CheckBox
            sub2Measure.isChecked = isChecked
            MyApp.roomDatabase.measureDao().update(sub2Measure)
            addMeasures(isChecked, sub2Measure)
        }
    }

    // 可用
    private fun addMeasures(isChecked: Boolean, measure: Measure) {
        if (isChecked) {
            measureCheckList.add(measure.id)
        } else {
            measureCheckList.remove(measure.id)
        }
        fabUpload.isEnabled = measureCheckList.isNotEmpty()
    }

    // 同步表
    private suspend fun syncMeasure() {
        showTip("点表同步中")
        val syncResult = resultTryContext {
            val map = hashMapOf<String, Any>()
            map["id"] = currentTaskId
            map["mIds"] = MyApp.roomDatabase.typeDao().queryAll().map { it.id }.toLongArray()
            api.taskSyncStatus(map.jsonBody()).execute().body()
        }
        if (syncResult.code == API_SUCCESS_CODE) {
            withContext(Dispatchers.IO){
                val syncMeasure = arrayListOf<Measure>()
                val measureIds = arrayListOf<Long>()
                syncResult.data?.forEach {
                    if (it.s == "1") {
                        // 该点表全部调试通过
                        syncMeasure.addAll(MyApp.roomDatabase.typeDao().measures(it.mid))
                    } else {
                        // 该点表部分通过
                        measureIds.addAll(it.sub)
                    }
                }
                syncMeasure.addAll(MyApp.roomDatabase.measureDao().queryByIds(measureIds))
                syncMeasure.forEach {
                    it.isSuccessful = true
                    it.isDebugging = true
                }
                "点表数量:${syncMeasure.size}".debugLogInfo { "okhttp" }
                MyApp.roomDatabase.measureDao().update(syncMeasure)
            }
        } else {
            error(syncResult)
        }
        dismissTip()
    }

    override fun hasToolbar(): Boolean {
        return true
    }

    override fun hasBackIcon(): Boolean {
        return false
    }

    companion object {
        fun newInstance(): WorkFragment {
            return WorkFragment()
        }
    }

    override fun onBackPressedSupport(): Boolean {
        activity?.finish()
        return true
    }
}